home *** CD-ROM | disk | FTP | other *** search
- Title: TRI - 8088 routine CALLed from BASIC Steve Muenter
-
- comment *This routine produces polyphonic music with three
- voices. The frequencies and durations of the notes
- are passed to this routine in an integer array.
-
- Called from BASIC via:
-
- CALL TRI(TUNE%(0))
-
- Where:
-
- TUNE% is an integer array
-
- TUNE% is treated by TRI as data words with the three most
- significant bits identifying the type of data. 000 causes
- the routine to terminate and return to BASIC. 001 sets
- the duration of play of the voices before being updated.
- 010 sets the tempo of the playback. 011 is unused. 100
- sets the period for voice 1 which is slightly louder than
- the rest. 101 sets the period for voice 2. 110 sets the
- period for voice 3.
- *
-
- cseg segment
- assume CS:cseg, DS:cseg, ES:nothing
- ; db 0FDH ;indicates BLOAD file
- ; dw 0 ;segment--BASIC will use default
- ; dw 0 ;offset--specify in BLOAD command
- ; dw rtn_len ;length of the routine
-
- spkr_io equ 61H
-
- tri proc far
- push bp
- mov bp,sp
- mov ax,(bp+6) ;get address of TUNE%(0) off stack
- sub ax,2 ;required for first time in sort
- push ax ;save on stack
- mov ax,1FFFH ;default tempo data
- push ax ;save on stack
- push ax ;initialize tempo counter
- xor ax,ax ;must write 0 into voice count and
- mov bx,ax ; data registers
- mov dx,ax
- mov si,ax
- mov bp,ax
- mov di,ax
- mov es,ax
- ;
- ;This section sorts the tune data into the appropriate registers
- ;Voice period data is stored in ES for voice 1, DI for voice 2,
- ;and SI for voice 3. The voice period count is stored in BX for
- ;voice 1, DX for voice 2, and BP for voice 3.
- ;
- sort: push bx
- push dx
- push bp
-
- sort_1: mov bp,sp
- mov bx,(bp+10) ;get tune pointer
- add bx,2 ;point to next tune data
- mov (bp+10),bx ;restore updated tune pointer
- mov ax,(bx) ;get tune data in AX
- mov dx,ax ;make a copy in DX
- and dx,1FFFH ;strip off 3 data type bits
- shl ax,1 ;move msb into carry bit
- jnc sort_4 ;jump if end, duration, or tempo data
- shl ax,1 ;move 2nd msb into carry bit
- jc sort_3 ;jump if voice 3 data
- shl ax,1 ;move 3rd msb into carry bit
- jc sort_2 ;jump if voice 2 data
- mov es,dx ;store voice 1 data in ES
- jmp sort_1
- sort_2: mov di,dx ;store voice 2 data in DI
- jmp sort_1
- sort_3: mov si,dx ;store voice 3 data in SI
- jmp sort_1 ;ignore
- sort_4: shl ax,1 ;move 2nd msb into carry bit
- jnc sort_6 ;jump if end or duration bit
- jnc sort_6 ;jump if end or duration data
- shl ax,1
- jnc sort_5 ;jump if tempo data
- jmp sort_1 ;ignore
- sort_5: mov (bp+8),dx ;store tempo
- mov (bp+6),dx ;initialize tempo counter
- jmp sort_1
- sort_6: shl ax,1 ;move 3rd msb into carry
- jc sort_7 ;jump if duration
- jmp end
- sort_7: mov cx,dx ;store duration data
- pop bp
- pop dx
- pop bx
- cli ;turn off interrupts during play
- loop: pop ax ;get current tempo count
- dec ax ;subtract 1
- push ax ;restore tempo count
- jnz play ;jump if some tempo remains
- pop ax ;reset tempo counter
- pop ax
- push ax
- push ax
- loop play ;decrement duration counter
- sti ;turn ints back on during sort
- jmp sort ;get new tune data if duration up
- ;
- ;This routine plays the notes until the duration counter in CX
- ;reaches zero. At that time, the new data is sorted.
- ;
- play: add bx,si ;add voice 3 data to count
- rol bx,1 ;get msb of voice 3 count
- mov al,12H ;keeps keyboard clk on and
- rcl al,1 ; casette motor relay off
- rcl al,1
- out spkr_io,al ;output voice 3 state to speaker
- ror bx,1 ;restore bx to original state
- add dx,di ;add voice 2 data to count
- rol dx,1
- mov al,12H
- rcl al,1
- rcl al,1
- out spkr_io,al
- ror dx,1
- mov ax,es
- add bp,ax ;add voice 1 data to count
- rol bp,1
- mov al,12H
- rcl al,1
- rcl al,1
- out spkr_io,al
- ror bp,1
- jmp loop
- end: add sp,12
- pop bp
- mov ax,cs
- mov es,ax
- ret 2
- tri endp
- rtn_len equ $-tri ;length of routine for header
- cseg ends
- end tri
-